package org.example.java.util.concurrency;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author juntao zhang
 */
public class ConditionTest {
  private Lock lock = new ReentrantLock();
  private Condition condition = lock.newCondition();

  private void run() throws Exception {

    ExecutorService executor = Executors.newCachedThreadPool();
    executor.execute(new Runnable() {
      @Override
      public void run() {
        System.out.println("t1 begin!");
        lock.lock();
        System.out.println("t1 locked!");
        try {
          System.out.println("t1 begin sleep!");
          Thread.sleep(1000 * 2L);
          System.out.println("t1 begin wait!");
          condition.await();
          System.out.println("t1 wait end!");
        } catch (InterruptedException e) {
          e.printStackTrace();
        } finally {
          lock.unlock();
        }
        System.out.println("t1 end!");
      }
    });

    executor.execute(new Runnable() {
      @Override
      public void run() {
        System.out.println("t2 begin!");
        try {
          Thread.sleep((long) 1000);
          System.out.println("t2 try lock " + lock.tryLock());
          if (lock.tryLock(2, TimeUnit.SECONDS)) {
            condition.signalAll();
            System.out.println("t2 notify t1");
            lock.unlock();
            System.out.println("t2 unlock");
          }

        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("t2 end");
      }
    });

    executor.awaitTermination(5, TimeUnit.SECONDS);
    executor.shutdown();
    System.out.println("==end==");

  }


  public static void main(String[] args) throws Exception {
    new ConditionTest().run();
  }
}
